package com.zh.generator;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;


@Data
public class CodeGenerator {

    /**
     * 代码生成的包名
     */
    private String packageName;
    /**
     * 代码后端生成的地址
     */
    private String packageDir;
    /**
     * 代码所在服务名
     */
    private String serviceName;

    public String controllerModuleName;

    public String controllerPackageName;

    /**
     * 需要去掉的表前缀
     */
    private String[] tablePrefix = {};
    /**
     * 需要生成的表名(两者只能取其一)
     */
    private String[] includeTables = {};
    /**
     * 需要排除的表名(两者只能取其一)
     */
    private String[] excludeTables = {};
    /**
     * 基础业务字段
     */
    private String[] superEntityColumns = {"timeCreated", "timeUpdated", "id"};

    private Boolean hasSuperEntity = Boolean.TRUE;

    /**
     * 数据库驱动名
     */
    private String driverName;
    /**
     * 数据库链接地址
     */
    private String url;
    /**
     * 数据库用户名
     */
    private String username;
    /**
     * 数据库密码
     */
    private String password;

    /**
     * 代码生成执行
     */
    public void run() {

        String servicePackage = serviceName.split("-").length > 1 ? serviceName.split("-")[1] : serviceName;
        Map<String, Object> customMap = new HashMap<>();
        customMap.put("serviceName", serviceName);
        customMap.put("servicePackage", servicePackage);
        customMap.put("servicePackageLowerCase", servicePackage.toLowerCase());

        Map<OutputFile, String> pathInfo = new HashMap<>();
        pathInfo.put(OutputFile.xml, getXMLOutputDir());
        pathInfo.put(OutputFile.entity, getOutputDir() + "/" + packageName.replace(".", "/") + "/entity");
        pathInfo.put(OutputFile.service, "");
        pathInfo.put(OutputFile.serviceImpl, getOutputDir() + "/" + packageName.replace(".", "/") + "/repository");
        pathInfo.put(OutputFile.mapper, getOutputDir() + "/" + packageName.replace(".", "/") + "/mapper");

        if(controllerPackageName!=null){
            pathInfo.put(OutputFile.controller, getControllerOutputDir() + "/" + controllerPackageName.replace(".", "/") + "/controller");
        }else{
            pathInfo.put(OutputFile.controller, "");
        }

        FastAutoGenerator.create(this.url, this.username, this.password)
                .globalConfig(builder -> builder.author("zh")
                        .dateType(DateType.TIME_PACK)
                        .enableSwagger()
                        .outputDir(getOutputDir()).
                        disableOpenDir())
                .packageConfig(builder -> builder.pathInfo(pathInfo)
                        .parent("")
                        .entity(this.packageName+".entity")
                        .service(this.packageName+".repository")
                        .serviceImpl(this.packageName+".repository")
                        .mapper(this.packageName+".mapper")
                        .xml(this.packageName+".mapper")
                        .controller(this.controllerPackageName+".controller"))
                .strategyConfig(builder -> builder.addTablePrefix(tablePrefix).addInclude(includeTables).addExclude(excludeTables)
                        .entityBuilder().fileOverride().naming(NamingStrategy.underline_to_camel).columnNaming(NamingStrategy.underline_to_camel).enableLombok().superClass("com.zh.generator.core.BaseDO").formatFileName("%sDO").addSuperEntityColumns(superEntityColumns)
                        .controllerBuilder()
                        .serviceBuilder()
                        .superServiceClass(IService.class).formatServiceFileName("I%sRepository")
                        .superServiceImplClass("com.zh.generator.core.BaseRepository").formatServiceImplFileName("%sRepository")
                        .mapperBuilder().superClass("com.zh.generator.core.DefaultMapper")
                        .enableMapperAnnotation().enableBaseResultMap().enableBaseColumnList()
                        .formatMapperFileName("%sMapper").formatXmlFileName("%sMapper")
                )
                .templateConfig(builder -> builder.disable(TemplateType.ENTITY)
                        .entity("/templates/entity.java.vm")
                        .service("/templates/service.java.vm")
                        .serviceImpl("/templates/serviceImpl.java.vm")
                        .mapper("/templates/mapper.java.vm")
                        .xml("/templates/mapper.xml.vm")
                        .controller("/templates/controller.java.vm"))
                .injectionConfig(builder -> builder
                        .beforeOutputFile(
                                (tableInfo, objectMap) -> System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size())
                        ).customMap(customMap).fileOverride()
                )
                .templateEngine(new VelocityTemplateEngine() {

                })
                .execute();

    }

    /**
     * 生成到项目中
     *
     * @return outputDir
     */
    public String getOutputDir() {
        return (StrUtil.isBlank(packageDir) ? System.getProperty("user.dir") : packageDir) + "/" + serviceName + "/src/main/java";
    }

    public String getXMLOutputDir() {
        return (StrUtil.isBlank(packageDir) ? System.getProperty("user.dir") : packageDir) + "/" + serviceName + "/src/main/resources/mapper";
    }

    public String getControllerOutputDir() {
        return (StrUtil.isBlank(packageDir) ? System.getProperty("user.dir") : packageDir) + "/" + controllerModuleName + "/src/main/java";
    }
}
